/*
 *  SessionData.java
 * 
 *  Created on Apr 24, 2008, 11:28:30 PM
 */
package pl.edu.agh.ssm.monitor.data;

import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

/**
 * Represents session data in form that conforms to SDP. 
 * It has two inner classes for session activation time description and media description, respectively: TimeDescription and MediaDescription.
 * @author aneezka
 */
public class SessionDescription implements SessionData {

    public SessionDescription() {
    }

    public String getId() {
        return owner;
    }
    
    public String getName() {
        return name;
    }
    
    public SessionType getType() {
        return type;
    }

    public String getDescription() {
        return description;
    }

    public String getEmail() {
        return email;
    }

    public String getPhone() {
        return phone;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public void setType(SessionType type) {
        this.type = type;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getOwner() {
        return owner;
    }

    public void setOwner(String owner) {
        this.owner = owner;
    }

    public List<String> getBandwidth() {
        return bandwidth;
    }

    public void addBandwidth(String bandwidth) {
        this.bandwidth.add(bandwidth);
    }

    public String getUri() {
        return uri;
    }

    public void setUri(String uri) {
        this.uri = uri;
    }
    
    public void setVersion(String version) {
        this.version = version;
    }
    
    public String getVersion() {
        return version;
    }

    public String getConnectionInfo() {
        return connectionInfo;
    }

    public void setConnectionInfo(String connectionInfo) {
        this.connectionInfo = connectionInfo;
    }

    public String getTimeZoneAdjustment() {
        return timeZoneAdjustment;
    }

    public void setTimeZoneAdjustment(String timeZoneAdj) {
        this.timeZoneAdjustment = timeZoneAdj;
    }

    public String getEncryptionKey() {
        return encryptionKey;
    }

    public void setEncryptionKey(String encryptionKey) {
        this.encryptionKey = encryptionKey;
    }

    public List<String> getSessionAttributes() {
        return sessionAttributes;
    }

    public void addSessionAttribute(String sessionAttribute) {
        sessionAttributes.add(sessionAttribute);
    }

    public List<TimeDescription> getTimeDescriptions() {
        return timeDescriptions;
    }

    public void addTimeDescription(TimeDescription timeDescription) {
        timeDescriptions.add(timeDescription);
    }

    public List<MediaDescription> getMediaDescriptions() {
        return mediaDescriptions;
    }

    public void addMediaDescription(MediaDescription mediaDescription) {
        mediaDescriptions.add(mediaDescription);
    }
    
    @Override
    public String toString() {
        return name;
    }

    /**
     * Session time description
     */
    static public class TimeDescription {

        public TimeDescription() {
        }

        public Date getStartDate() {
            return startDate;
        }

        public void setStartDate(Date startDate) {
            this.startDate = startDate;
        }

        public Date getEndDate() {
            return endDate;
        }

        public void setEndDate(Date endDate) {
            this.endDate = endDate;
        }

        public String getRepeatInterval() {
            return repeatInterval;
        }

        public void setRepeatInterval(String repeatInterval) {
            this.repeatInterval = repeatInterval;
        }

        public String getActiveDuration() {
            return activeDuration;
        }

        public void setActiveDuration(String activeDuration) {
            this.activeDuration = activeDuration;
        }

        public List<String> getOffsets() {
            return offsets;
        }

        public void addOffset(String offset) {
            this.offsets.add(offset);
        }
        
        @Override
        public String toString() {
            return startDate.toString();
        }
        
        public HashMap<Date, Date> getNearestSessionsDates() {
            //Date initial = startDate;
            long repeatMiliseconds = 0;
            long durationMiliseconds = 0;
            List<Long> offsetsMiliseconds = new LinkedList<Long>();
            List<Date> initialStartDates = new LinkedList<Date>();
            List<Date> initialEndDates = new LinkedList<Date>();
            HashMap<Date, Date> result = new HashMap<Date, Date>();
            boolean cont = true;
            if (repeatInterval != null && !repeatInterval.trim().equals("")) {
                repeatMiliseconds = getSeconds(repeatInterval) * 1000L;
            } else {
                cont = false;
            }
            if (activeDuration != null && !activeDuration.trim().equals("")) {
                durationMiliseconds = getSeconds(activeDuration) * 1000L;
            } else {
                cont = false;
            }
            if (offsets.size() > 0) {
                for (String s : offsets) {
                    offsetsMiliseconds.add(getSeconds(s) * 1000L);
                }
            } else {
                cont = false;
            }
            if (cont) {
                for (Long o : offsetsMiliseconds) {
                    Date start = new Date(startDate.getTime() + o);
                    Date end = new Date(start.getTime() + durationMiliseconds);
                    initialStartDates.add(start);
                    initialEndDates.add(end);
                    result.put(start, end);
                }
                int counter = 0;
                Date currentEndDate = startDate;
                long intervalToAdd = repeatMiliseconds;
                while (counter < 20 && currentEndDate.compareTo(endDate) < 0) {
                    for (int i = 0; i < initialStartDates.size(); i++) {
                        Date newStart = new Date(initialStartDates.get(i).getTime() + intervalToAdd);
                        Date newEnd = new Date(initialEndDates.get(i).getTime() + intervalToAdd);
                        currentEndDate = newEnd;
                        result.put(newStart, newEnd);
                        counter++;
                    }
                    intervalToAdd += repeatMiliseconds;
                }
            } else {
                result.put(startDate, endDate);
            }
            return result;
        }
        
        private long getSeconds(String string) {
            long result;
            long multiplier;
            boolean cut = true;
            if (string.endsWith("d")) {
                multiplier = 86400L;
            } else if (string.endsWith("h")) {
                multiplier = 3600L;
            } else if (string.endsWith("m")) {
                multiplier = 60L;
            } else if (string.endsWith("s")) {
                multiplier = 1L;
            } else {
                cut = false;
                multiplier = 1L;
            }
            if (cut) {
                string = string.substring(0, string.length() - 1);
            }
            try {
                result = Long.parseLong(string);
                result *= multiplier;
                return result;
            } catch (NumberFormatException e) {
                return -1;
            }
        }
        
        private Date startDate;
        private Date endDate;
        private String repeatInterval;
        private String activeDuration;
        private List<String> offsets = new LinkedList<String>();
    }

    /**
     * Session media description
     */
    static public class MediaDescription {

        public MediaDescription() {

        }

        public String getMediaName() {
            return mediaName;
        }

        public void setMediaName(String mediaName) {
            this.mediaName = mediaName;
        }

        public String getTransportAddress() {
            return transportAddress;
        }

        public void setTransportAddress(String transportAddress) {
            this.transportAddress = transportAddress;
        }

        public String getMediaTitle() {
            return mediaTitle;
        }

        public void setMediaTitle(String mediaTitle) {
            this.mediaTitle = mediaTitle;
        }

        public String getConnectionInfo() {
            return connectionInfo;
        }

        public void setConnectionInfo(String connectionInfo) {
            this.connectionInfo = connectionInfo;
        }

        public List<String> getBandwidth() {
            return bandwidth;
        }

        public void addBandwidth(String bandwidth) {
            this.bandwidth.add(bandwidth);
        }

        public String getEncryptionKey() {
            return encryptionKey;
        }

        public void setEncryptionKey(String encryptionKey) {
            this.encryptionKey = encryptionKey;
        }

        public List<String> getMediaAttributes() {
            return mediaAttributes;
        }

        public void addMediaAttribute(String mediaAttribute) {
            mediaAttributes.add(mediaAttribute);
        }
    	
		public SessionMediaType getMediaType() {
			return mediaType;
		}

		public void setMediaType(SessionMediaType mediaType) {
			this.mediaType = mediaType;
		}

		public String getMediaAddress() {
			return mediaAddress;
		}

		public void setMediaAddress(String mediaAddress) {
			this.mediaAddress = mediaAddress;
		}

		public int getMediaPort() {
			return mediaPort;
		}

		public void setMediaPort(int mediaPort) {
			this.mediaPort = mediaPort;
		}

		public int getPayloadType() {
			return payloadType;
		}

		public void setPayloadType(int payloadType) {
			this.payloadType = payloadType;
		}

		
		
		@Override
        public String toString() {
            return mediaName;
        }
        
        private String mediaName;
        private String transportAddress;
        private String mediaTitle;
        private String connectionInfo;
        private String encryptionKey;
        private List<String> bandwidth = new LinkedList<String>();
        private List<String> mediaAttributes = new LinkedList<String>();
        private SessionMediaType mediaType;
    	private String mediaAddress;
    	private int mediaPort;
    	private int payloadType;
        
    }
    
	public HashMap<Integer, SessionMedia> getRtpmap() {
		return rtpmap;
	}
	
	public void addMap(int key, SessionMedia value) {
		rtpmap.put(key, value);
	}

    
    private String name;
    private SessionType type;
    private String version;
    private String description;
    private String email;
    private String phone;
    private String owner;
    private String uri;
    private String connectionInfo;
    private String timeZoneAdjustment;
    private String encryptionKey;
    private List<String> bandwidth = new LinkedList<String>();
    private List<String> sessionAttributes = new LinkedList<String>();
    private List<TimeDescription> timeDescriptions = new LinkedList<TimeDescription>();
    private List<MediaDescription> mediaDescriptions = new LinkedList<MediaDescription>();
    private HashMap<Integer, SessionMedia> rtpmap =
		new HashMap<Integer, SessionMedia>();
}
